package com.chinaisafe.gateway.config;

import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.chinaisafe.base.common.enums.AnswerCodeEnum;
import com.chinaisafe.base.common.vo.Answer;
import com.chinaisafe.gateway.sdk.vo.request.Oauth2UserLoginReqVo;
import com.chinaisafe.gateway.sdk.vo.response.Oauth2UserLoginRespVo;
import com.chinaisafe.gateway.server.service.user.IGatewayUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * SaTokenConfigure
 * [Sa-Token 权限认证] 全局配置类
 *
 * @author xuefu.shu
 * @date 2024-07-03 10:42
 */
@Slf4j
@Configuration
public class SaTokenConfigure {

    @Resource
    private IGatewayUserService gatewayUserService;

    /**
     * 注册 [Sa-Token全局过滤器]
     */
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 指定 [拦截路由]
                .addInclude("/**")
                // 指定 [放行路由]
                .addExclude("/gateway/**")
                .addExclude("/oauth2/**")
                // 指定[认证函数]: 每次请求执行 
                .setAuth(auth -> {
                    if (log.isDebugEnabled()) {
                        log.debug("Sa reactor auth {}", auth);
                    }
                })
                // 指定[异常处理函数]：每次[认证函数]发生异常时执行此函数 
                .setError(e -> {
                    log.error("认证函数发生异常", e);
                    return Answer.create(AnswerCodeEnum.EXCEPTION, e.getMessage(), null);
                });
    }


    /**
     * 配置 Sa-OAuth2
     *
     * @param cfg 配置
     */
    @Autowired
    public void setSaOauth2Config(SaOAuth2Config cfg) {
        // 配置：未登录时返回的View
        cfg.setNotLoginView(() -> Answer.create(AnswerCodeEnum.NO_AUTH, AnswerCodeEnum.NO_AUTH.getMessage(), null))
                // 配置：登录处理函数
                .setDoLoginHandle((name, pwd) -> {
                    if (StrUtil.isNotBlank(name) && StrUtil.isNotBlank(pwd)) {
                        Oauth2UserLoginReqVo userLoginReqVo = new Oauth2UserLoginReqVo();
                        userLoginReqVo.setUserName(name);
                        userLoginReqVo.setPassword(pwd);

                        Answer<Oauth2UserLoginRespVo> userInfo = gatewayUserService.getOauth2LoginUserInfo(userLoginReqVo);
                        if (userInfo.getCode() == AnswerCodeEnum.SUCCESS.getCode()) {
                            StpUtil.logout(userInfo.getData().getUserId());
                            String tokenValue = StpUtil.getTokenValue();
                            return Answer.successWithData(tokenValue);
                        } else {
                            return Answer.create(AnswerCodeEnum.USER_NOT_FIND, AnswerCodeEnum.USER_NOT_FIND.getMessage(), null);
                        }
                    }
                    return Answer.create(AnswerCodeEnum.PARAM_TYPE_ERROR, "用户或密码参数不完整", null);

                })
                // 配置：确认授权时返回的View
                .setConfirmView((clientId, scope) -> {
                    if (log.isDebugEnabled()) {
                        log.info("确认授权时返回的View");
                    }
                    return "";
                });
    }

}
